/*
 * @Author: unicorn-get-happy unicorn_boy@163.com
 * @Date: 2023-11-24 23:04:00
 * @LastEditors: unicorn-get-happy unicorn_boy@163.com
 * @LastEditTime: 2023-11-25 12:34:53
 * @FilePath: \esp32\components\lvgl_esp32_drivers\lvgl_touch\cst816t.c
 * @Description: cst816 触摸驱动
 *
 * Copyright (c) 2023 by unicorn_boy@163.com, All Rights Reserved.
 */

#include <esp_log.h>

#ifdef LV_LVGL_H_INCLUDE_SIMPLE
#include <lvgl.h>
#else
#include <lvgl/lvgl.h>
#endif

#include "cst816t.h"
#include "lvgl_i2c/i2c_manager.h"
#include "lvgl_helpers.h"

static const char *TAG = "CST816T";

static uint8_t cst816t_read_len(uint8_t reg_addr, uint8_t *data, uint8_t len)
{
    uint8_t res = 0;
    res = i2c_master_write_read_device(CONFIG_LV_I2C_TOUCH_PORT, CST816T_ADDR, &reg_addr, 1, data, len, 100 / portTICK_PERIOD_MS);

    return res;
}

static esp_err_t  cst816t_get_touch_points_num(uint8_t *touch_points_num)
{
    uint8_t res = 0;
    res = cst816t_read_len(0x02, touch_points_num, 1);
    return res;
}

static esp_err_t cst816t_read_pos(uint8_t *touch_points_num, uint16_t *x, uint16_t *y)
{
    uint8_t data[4];

    cst816t_get_touch_points_num(touch_points_num);
    if (0 == *touch_points_num) {
        *x = 0;
        *y = 0;
        return 1;
    } else {
        cst816t_read_len(0x03, data, 4);

        *x = ((data[0] & 0x0f) << 8) | data[1];
        *y = ((data[2] & 0x0f) << 8) | data[3];
    }

    ESP_LOGI(TAG, "X=%d Y=%d", *x, *y);
    return ESP_OK;
}

static esp_err_t cst816t_i2c_read(uint8_t slave_addr, uint16_t register_addr, uint8_t *data_buf, uint8_t len)
{
    return lvgl_i2c_read(CONFIG_LV_I2C_TOUCH_PORT, slave_addr, register_addr, data_buf, len);
}

void cst816t_init()
{
    ESP_LOGI(TAG, "Checking for CST816T Touch Controller ");

    uint8_t data_buf[10];
    esp_err_t ret;

    // Only show error the first time
    if ((ret = cst816t_i2c_read(CST816T_ADDR, 0x15, data_buf, 1) != ESP_OK)) {
        vTaskDelay(pdMS_TO_TICKS(10));
        ESP_LOGE(TAG, "Error reading from device: %s", esp_err_to_name(ret));
    }
    if ((ret = cst816t_i2c_read(CST816T_ADDR, 0xa7, data_buf, 1) != ESP_OK)) {
        ESP_LOGE(TAG, "Error reading from device: %s", esp_err_to_name(ret));
        ESP_LOGE(TAG, "device ID: %02x", data_buf[0]);
    }
}

bool cst816t_read(lv_indev_drv_t *drv, lv_indev_data_t *data)
{
    uint8_t touch_points_num = 0;
    uint16_t x = 0;
    uint16_t y = 0;

    cst816t_read_pos(&touch_points_num, &x, &y);

#if CONFIG_LV_CST816T_INVERT_X
    x = LV_HOR_RES_MAX - x;
#endif
#if CONFIG_LV_CST816T_INVERT_Y
    y = LV_VER_RES_MAX - y;
#endif
#if CONFIG_LV_CST816T_SWAPXY
    int16_t swap_buf = x;
    x = y;
    y = swap_buf;
#endif

    data->point.x = x;
    data->point.y = y;
    if (touch_points_num > 0) {
        data->state = LV_INDEV_STATE_PR;
    } else {
        data->state = LV_INDEV_STATE_REL;
    }

    return false;
}
